home *** CD-ROM | disk | FTP | other *** search
/ Acorn RISC PD-CD 1 / Acorn RISC PD-CD 1.iso / languages / gawk / c / eval < prev    next >
Encoding:
Text File  |  1990-02-20  |  28.8 KB  |  1,140 lines

  1. /*
  2.  * eval.c - gawk parse tree interpreter 
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. extern void do_print();
  29. extern void do_printf();
  30. extern NODE *do_match();
  31. extern NODE *do_sub();
  32. extern NODE *do_getline();
  33. extern NODE *concat_exp();
  34. extern int in_array();
  35. extern void do_delete();
  36.  
  37. static int eval_condition();
  38. static NODE *op_assign();
  39. static NODE *func_call();
  40. static NODE *match_op();
  41.  
  42. NODE *_t;        /* used as a temporary in macros */
  43. #ifdef MSDOS
  44. double _msc51bug;    /* to get around a bug in MSC 5.1 */
  45. #endif
  46. NODE *ret_node;
  47.  
  48. /* More of that debugging stuff */
  49. #ifdef    DEBUG
  50. #define DBG_P(X) print_debug X
  51. #else
  52. #define DBG_P(X)
  53. #endif
  54.  
  55. /* Macros and variables to save and restore function and loop bindings */
  56. /*
  57.  * the val variable allows return/continue/break-out-of-context to be
  58.  * caught and diagnosed
  59.  */
  60. #define PUSH_BINDING(stack, x, val) (memcpy ((char *)(stack), (char *)(x), sizeof (jmp_buf)), val++)
  61. #define RESTORE_BINDING(stack, x, val) (memcpy ((char *)(x), (char *)(stack), sizeof (jmp_buf)), val--)
  62.  
  63. static jmp_buf loop_tag;    /* always the current binding */
  64. static int loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  65. static int func_tag_valid = 0;
  66. static jmp_buf func_tag;
  67. extern int exiting, exit_val;
  68.  
  69. /*
  70.  * This table is used by the regexp routines to do case independant
  71.  * matching. Basically, every ascii character maps to itself, except
  72.  * uppercase letters map to lower case ones. This table has 256
  73.  * entries, which may be overkill. Note also that if the system this
  74.  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  75.  * defined to the linker, so gawk should not load.
  76.  *
  77.  * Do NOT make this array static, it is used in several spots, not
  78.  * just in this file.
  79.  */
  80. #if 'a' == 97    /* it's ascii */
  81. char casetable[] = {
  82.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  83.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  84.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  85.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  86.     /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  87.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  88.     /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  89.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  90.     /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  91.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  92.     /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  93.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  94.     /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  95.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  96.     /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  97.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  98.     /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  99.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  100.     /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  101.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  102.     /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  103.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  104.     /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  105.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  106.     /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  107.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  108.     /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  109.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  110.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  111.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  112.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  113.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  114.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  115.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  116.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  117.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  118.     '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  119.     '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  120.     '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  121.     '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  122.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  123.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  124.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  125.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  126. };
  127. #else
  128. #include "You lose. You will need a translation table for your character set."
  129. #endif
  130.  
  131. /*
  132.  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  133.  * statement 
  134.  */
  135. int
  136. interpret(tree)
  137. NODE *tree;
  138. {
  139.     volatile jmp_buf loop_tag_stack; /* shallow binding stack for loop_tag */
  140.     static jmp_buf rule_tag;/* tag the rule currently being run, for NEXT
  141.                  * and EXIT statements.  It is static because
  142.                  * there are no nested rules */
  143.     register NODE *t = NULL;/* temporary */
  144.     volatile NODE **lhs;    /* lhs == Left Hand Side for assigns, etc */
  145.     volatile struct search *l;    /* For array_for */
  146.     volatile NODE *stable_tree;
  147.  
  148.     if (tree == NULL)
  149.         return 1;
  150.     sourceline = tree->source_line;
  151.     source = tree->source_file;
  152.     switch (tree->type) {
  153.     case Node_rule_list:
  154.         for (t = tree; t != NULL; t = t->rnode) {
  155.             tree = t->lnode;
  156.         /* FALL THROUGH */
  157.     case Node_rule_node:
  158.             sourceline = tree->source_line;
  159.             source = tree->source_file;
  160.             switch (setjmp(rule_tag)) {
  161.             case 0:    /* normal non-jump */
  162.                 /* test pattern, if any */
  163.                 if (tree->lnode == NULL 
  164.                     || eval_condition(tree->lnode)) {
  165.                     DBG_P(("Found a rule", tree->rnode));
  166.                     if (tree->rnode == NULL) {
  167.                         /*
  168.                          * special case: pattern with
  169.                          * no action is equivalent to
  170.                          * an action of {print}
  171.                          */
  172.                         NODE printnode;
  173.  
  174.                         printnode.type = Node_K_print;
  175.                         printnode.lnode = NULL;
  176.                         printnode.rnode = NULL;
  177.                         do_print(&printnode);
  178.                     } else if (tree->rnode->type == Node_illegal) {
  179.                         /*
  180.                          * An empty statement
  181.                          * (``{ }'') is different
  182.                          * from a missing statement.
  183.                          * A missing statement is
  184.                          * equal to ``{ print }'' as
  185.                          * above, but an empty
  186.                          * statement is as in C, do
  187.                          * nothing.
  188.                          */
  189.                     } else
  190.                         (void) interpret(tree->rnode);
  191.                 }
  192.                 break;
  193.             case TAG_CONTINUE:    /* NEXT statement */
  194.                 return 1;
  195.             case TAG_BREAK:
  196.                 return 0;
  197.             default:
  198.                 cant_happen();
  199.             }
  200.             if (t == NULL)
  201.                 break;
  202.         }
  203.         break;
  204.  
  205.     case Node_statement_list:
  206.         for (t = tree; t != NULL; t = t->rnode) {
  207.             DBG_P(("Statements", t->lnode));
  208.             (void) interpret(t->lnode);
  209.         }
  210.         break;
  211.  
  212.     case Node_K_if:
  213.         DBG_P(("IF", tree->lnode));
  214.         if (eval_condition(tree->lnode)) {
  215.             DBG_P(("True", tree->rnode->lnode));
  216.             (void) interpret(tree->rnode->lnode);
  217.         } else {
  218.             DBG_P(("False", tree->rnode->rnode));
  219.             (void) interpret(tree->rnode->rnode);
  220.         }
  221.         break;
  222.  
  223.     case Node_K_while:
  224.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  225.  
  226.         DBG_P(("WHILE", tree->lnode));
  227.         stable_tree = tree;
  228.         while (eval_condition(stable_tree->lnode)) {
  229.             switch (setjmp(loop_tag)) {
  230.             case 0:    /* normal non-jump */
  231.                 DBG_P(("DO", stable_tree->rnode));
  232.                 (void) interpret(stable_tree->rnode);
  233.                 break;
  234.             case TAG_CONTINUE:    /* continue statement */
  235.                 break;
  236.             case TAG_BREAK:    /* break statement */
  237.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  238.                 return 1;
  239.             default:
  240.                 cant_happen();
  241.             }
  242.         }
  243.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  244.         break;
  245.  
  246.     case Node_K_do:
  247.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  248.         stable_tree = tree;
  249.         do {
  250.             switch (setjmp(loop_tag)) {
  251.             case 0:    /* normal non-jump */
  252.                 DBG_P(("DO", stable_tree->rnode));
  253.                 (void) interpret(stable_tree->rnode);
  254.                 break;
  255.             case TAG_CONTINUE:    /* continue statement */
  256.                 break;
  257.             case TAG_BREAK:    /* break statement */
  258.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  259.                 return 1;
  260.             default:
  261.                 cant_happen();
  262.             }
  263.             DBG_P(("WHILE", stable_tree->lnode));
  264.         } while (eval_condition(stable_tree->lnode));
  265.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  266.         break;
  267.  
  268.     case Node_K_for:
  269.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  270.         DBG_P(("FOR", tree->forloop->init));
  271.         (void) interpret(tree->forloop->init);
  272.         DBG_P(("FOR.WHILE", tree->forloop->cond));
  273.         stable_tree = tree;
  274.         while (eval_condition(stable_tree->forloop->cond)) {
  275.             switch (setjmp(loop_tag)) {
  276.             case 0:    /* normal non-jump */
  277.                 DBG_P(("FOR.DO", stable_tree->lnode));
  278.                 (void) interpret(stable_tree->lnode);
  279.                 /* fall through */
  280.             case TAG_CONTINUE:    /* continue statement */
  281.                 DBG_P(("FOR.INCR", stable_tree->forloop->incr));
  282.                 (void) interpret(stable_tree->forloop->incr);
  283.                 break;
  284.             case TAG_BREAK:    /* break statement */
  285.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  286.                 return 1;
  287.             default:
  288.                 cant_happen();
  289.             }
  290.         }
  291.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  292.         break;
  293.  
  294.     case Node_K_arrayfor:
  295. #define hakvar forloop->init
  296. #define arrvar forloop->incr
  297.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  298.         DBG_P(("AFOR.VAR", tree->hakvar));
  299.         lhs = (volatile NODE **) get_lhs(tree->hakvar, 1);
  300.         t = tree->arrvar;
  301.         if (t->type == Node_param_list)
  302.             t = stack_ptr[t->param_cnt];
  303.         stable_tree = tree;
  304.         for (l = assoc_scan(t); l; l = assoc_next((struct search *)l)) {
  305.             deref = *((NODE **) lhs);
  306.             do_deref();
  307.             *lhs = dupnode(l->retval);
  308.             if (field_num == 0)
  309.                 set_record(fields_arr[0]->stptr,
  310.                     fields_arr[0]->stlen);
  311.             DBG_P(("AFOR.NEXTIS", *lhs));
  312.             switch (setjmp(loop_tag)) {
  313.             case 0:
  314.                 DBG_P(("AFOR.DO", stable_tree->lnode));
  315.                 (void) interpret(stable_tree->lnode);
  316.             case TAG_CONTINUE:
  317.                 break;
  318.  
  319.             case TAG_BREAK:
  320.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  321.                 field_num = -1;
  322.                 return 1;
  323.             default:
  324.                 cant_happen();
  325.             }
  326.         }
  327.         field_num = -1;
  328.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  329.         break;
  330.  
  331.     case Node_K_break:
  332.         DBG_P(("BREAK", NULL));
  333.         if (loop_tag_valid == 0)
  334.             fatal("unexpected break");
  335.         longjmp(loop_tag, TAG_BREAK);
  336.         break;
  337.  
  338.     case Node_K_continue:
  339.         DBG_P(("CONTINUE", NULL));
  340.         if (loop_tag_valid == 0)
  341.             fatal("unexpected continue");
  342.         longjmp(loop_tag, TAG_CONTINUE);
  343.         break;
  344.  
  345.     case Node_K_print:
  346.         DBG_P(("PRINT", tree));
  347.         do_print(tree);
  348.         break;
  349.  
  350.     case Node_K_printf:
  351.         DBG_P(("PRINTF", tree));
  352.         do_printf(tree);
  353.         break;
  354.  
  355.     case Node_K_next:
  356.         DBG_P(("NEXT", NULL));
  357.         longjmp(rule_tag, TAG_CONTINUE);
  358.         break;
  359.  
  360.     case Node_K_exit:
  361.         /*
  362.          * In A,K,&W, p. 49, it says that an exit statement "...
  363.          * causes the program to behave as if the end of input had
  364.          * occurred; no more input is read, and the END actions, if
  365.          * any are executed." This implies that the rest of the rules
  366.          * are not done. So we immediately break out of the main loop.
  367.          */
  368.         DBG_P(("EXIT", NULL));
  369.         exiting = 1;
  370.         if (tree) {
  371.             t = tree_eval(tree->lnode);
  372.             exit_val = (int) force_number(t);
  373.         }
  374.         free_temp(t);
  375.         longjmp(rule_tag, TAG_BREAK);
  376.         break;
  377.  
  378.     case Node_K_return:
  379.         DBG_P(("RETURN", NULL));
  380.         t = tree_eval(tree->lnode);
  381.         ret_node = dupnode(t);
  382.         free_temp(t);
  383.         longjmp(func_tag, TAG_RETURN);
  384.         break;
  385.  
  386.     default:
  387.         /*
  388.          * Appears to be an expression statement.  Throw away the
  389.          * value. 
  390.          */
  391.         DBG_P(("E", NULL));
  392.         t = tree_eval(tree);
  393.         free_temp(t);
  394.         break;
  395.     }
  396.     return 1;
  397. }
  398.  
  399. /* evaluate a subtree, allocating strings on a temporary stack. */
  400.  
  401. NODE *
  402. r_tree_eval(tree)
  403. NODE *tree;
  404. {
  405.     register NODE *r, *t1, *t2;    /* return value & temporary subtrees */
  406.     register NODE **lhs;
  407.     int di;
  408.     AWKNUM x, x2;
  409.     long lx;
  410.     extern NODE **fields_arr;
  411.  
  412.     source = tree->source_file;
  413.     sourceline = tree->source_line;
  414.     switch (tree->type) {
  415.     case Node_and:
  416.         DBG_P(("AND", tree));
  417.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  418.                         && eval_condition(tree->rnode)));
  419.  
  420.     case Node_or:
  421.         DBG_P(("OR", tree));
  422.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  423.                         || eval_condition(tree->rnode)));
  424.  
  425.     case Node_not:
  426.         DBG_P(("NOT", tree));
  427.         return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
  428.  
  429.         /* Builtins */
  430.     case Node_builtin:
  431.         DBG_P(("builtin", tree));
  432.         return ((*tree->proc) (tree->subnode));
  433.  
  434.     case Node_K_getline:
  435.         DBG_P(("GETLINE", tree));
  436.         return (do_getline(tree));
  437.  
  438.     case Node_in_array:
  439.         DBG_P(("IN_ARRAY", tree));
  440.         return tmp_number((AWKNUM) in_array(tree->lnode, tree->rnode));
  441.  
  442.     case Node_func_call:
  443.         DBG_P(("func_call", tree));
  444.         return func_call(tree->rnode, tree->lnode);
  445.  
  446.     case Node_K_delete:
  447.         DBG_P(("DELETE", tree));
  448.         do_delete(tree->lnode, tree->rnode);
  449.         return Nnull_string;
  450.  
  451.         /* unary operations */
  452.  
  453.     case Node_var:
  454.     case Node_var_array:
  455.     case Node_param_list:
  456.     case Node_subscript:
  457.     case Node_field_spec:
  458.         DBG_P(("var_type ref", tree));
  459.         lhs = get_lhs(tree, 0);
  460.         field_num = -1;
  461.         deref = 0;
  462.         return *lhs;
  463.  
  464.     case Node_unary_minus:
  465.         DBG_P(("UMINUS", tree));
  466.         t1 = tree_eval(tree->subnode);
  467.         x = -force_number(t1);
  468.         free_temp(t1);
  469.         return tmp_number(x);
  470.  
  471.     case Node_cond_exp:
  472.         DBG_P(("?:", tree));
  473.         if (eval_condition(tree->lnode)) {
  474.             DBG_P(("True", tree->rnode->lnode));
  475.             return tree_eval(tree->rnode->lnode);
  476.         }
  477.         DBG_P(("False", tree->rnode->rnode));
  478.         return tree_eval(tree->rnode->rnode);
  479.  
  480.     case Node_match:
  481.     case Node_nomatch:
  482.     case Node_regex:
  483.         DBG_P(("[no]match_op", tree));
  484.         return match_op(tree);
  485.  
  486.     case Node_func:
  487.         fatal("function `%s' called with space between name and (,\n%s",
  488.             tree->lnode->param,
  489.             "or used in other expression context");
  490.  
  491.     /* assignments */
  492.     case Node_assign:
  493.         DBG_P(("ASSIGN", tree));
  494.         r = tree_eval(tree->rnode);
  495.         lhs = get_lhs(tree->lnode, 1);
  496.         *lhs = dupnode(r);
  497.         free_temp(r);
  498.         do_deref();
  499.         if (field_num == 0)
  500.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  501.         field_num = -1;
  502.         return *lhs;
  503.  
  504.     /* other assignment types are easier because they are numeric */
  505.     case Node_preincrement:
  506.     case Node_predecrement:
  507.     case Node_postincrement:
  508.     case Node_postdecrement:
  509.     case Node_assign_exp:
  510.     case Node_assign_times:
  511.     case Node_assign_quotient:
  512.     case Node_assign_mod:
  513.     case Node_assign_plus:
  514.     case Node_assign_minus:
  515.         return op_assign(tree);
  516.     default:
  517.         break;    /* handled below */
  518.     }
  519.  
  520.     /* evaluate subtrees in order to do binary operation, then keep going */
  521.     t1 = tree_eval(tree->lnode);
  522.     t2 = tree_eval(tree->rnode);
  523.  
  524.     switch (tree->type) {
  525.     case Node_concat:
  526.         DBG_P(("CONCAT", tree));
  527.         t1 = force_string(t1);
  528.         t2 = force_string(t2);
  529.  
  530.         r = newnode(Node_val);
  531.         r->flags |= (STR|TEMP);
  532.         r->stlen = t1->stlen + t2->stlen;
  533.         r->stref = 1;
  534.         emalloc(r->stptr, char *, r->stlen + 1, "tree_eval");
  535.         memcpy(r->stptr, t1->stptr, t1->stlen);
  536.         memcpy(r->stptr + t1->stlen, t2->stptr, t2->stlen + 1);
  537.         free_temp(t1);
  538.         free_temp(t2);
  539.         return r;
  540.  
  541.     case Node_geq:
  542.     case Node_leq:
  543.     case Node_greater:
  544.     case Node_less:
  545.     case Node_notequal:
  546.     case Node_equal:
  547.         di = cmp_nodes(t1, t2);
  548.         free_temp(t1);
  549.         free_temp(t2);
  550.         switch (tree->type) {
  551.         case Node_equal:
  552.             DBG_P(("EQUAL", tree));
  553.             return tmp_number((AWKNUM) (di == 0));
  554.         case Node_notequal:
  555.             DBG_P(("NOT_EQUAL", tree));
  556.             return tmp_number((AWKNUM) (di != 0));
  557.         case Node_less:
  558.             DBG_P(("LESS_THAN", tree));
  559.             return tmp_number((AWKNUM) (di < 0));
  560.         case Node_greater:
  561.             DBG_P(("GREATER_THAN", tree));
  562.             return tmp_number((AWKNUM) (di > 0));
  563.         case Node_leq:
  564.             DBG_P(("LESS_THAN_EQUAL", tree));
  565.             return tmp_number((AWKNUM) (di <= 0));
  566.         case Node_geq:
  567.             DBG_P(("GREATER_THAN_EQUAL", tree));
  568.             return tmp_number((AWKNUM) (di >= 0));
  569.         default:
  570.             cant_happen();
  571.         }
  572.         break;
  573.     default:
  574.         break;    /* handled below */
  575.     }
  576.  
  577.     (void) force_number(t1);
  578.     (void) force_number(t2);
  579.  
  580.     switch (tree->type) {
  581.     case Node_exp:
  582.         DBG_P(("EXPONENT", tree));
  583.         if ((lx = t2->numbr) == t2->numbr) {    /* integer exponent */
  584.             if (lx == 0)
  585.                 x = 1;
  586.             else if (lx == 1)
  587.                 x = t1->numbr;
  588.             else {
  589.                 /* doing it this way should be more precise */
  590.                 for (x = x2 = t1->numbr; --lx; )
  591.                     x *= x2;
  592.             }
  593.         } else
  594.             x = pow((double) t1->numbr, (double) t2->numbr);
  595.         free_temp(t1);
  596.         free_temp(t2);
  597.         return tmp_number(x);
  598.  
  599.     case Node_times:
  600.         DBG_P(("MULT", tree));
  601.         x = t1->numbr * t2->numbr;
  602.         free_temp(t1);
  603.         free_temp(t2);
  604.         return tmp_number(x);
  605.  
  606.     case Node_quotient:
  607.         DBG_P(("DIVIDE", tree));
  608.         x = t2->numbr;
  609.         free_temp(t2);
  610.         if (x == (AWKNUM) 0)
  611.             fatal("division by zero attempted");
  612.             /* NOTREACHED */
  613.         else {
  614.             x = t1->numbr / x;
  615.             free_temp(t1);
  616.             return tmp_number(x);
  617.         }
  618.  
  619.     case Node_mod:
  620.         DBG_P(("MODULUS", tree));
  621.         x = t2->numbr;
  622.         free_temp(t2);
  623.         if (x == (AWKNUM) 0)
  624.             fatal("division by zero attempted in mod");
  625.             /* NOTREACHED */
  626.         lx = t1->numbr / x;    /* assignment to long truncates */
  627.         x2 = lx * x;
  628.         x = t1->numbr - x2;
  629.         free_temp(t1);
  630.         return tmp_number(x);
  631.  
  632.     case Node_plus:
  633.         DBG_P(("PLUS", tree));
  634.         x = t1->numbr + t2->numbr;
  635.         free_temp(t1);
  636.         free_temp(t2);
  637.         return tmp_number(x);
  638.  
  639.     case Node_minus:
  640.         DBG_P(("MINUS", tree));
  641.         x = t1->numbr - t2->numbr;
  642.         free_temp(t1);
  643.         free_temp(t2);
  644.         return tmp_number(x);
  645.  
  646.     default:
  647.         fatal("illegal type (%d) in tree_eval", tree->type);
  648.     }
  649.     return 0;
  650. }
  651.  
  652. /*
  653.  * This makes numeric operations slightly more efficient. Just change the
  654.  * value of a numeric node, if possible 
  655.  */
  656. void
  657. assign_number(ptr, value)
  658. NODE **ptr;
  659. AWKNUM value;
  660. {
  661.     extern NODE *deref;
  662.     register NODE *n = *ptr;
  663.  
  664. #ifdef DEBUG
  665.     if (n->type != Node_val)
  666.         cant_happen();
  667. #endif
  668.     if (n == Nnull_string) {
  669.         *ptr = make_number(value);
  670.         deref = 0;
  671.         return;
  672.     }
  673.     if (n->stref > 1) {
  674.         *ptr = make_number(value);
  675.         return;
  676.     }
  677.     if ((n->flags & STR) && (n->flags & (MALLOC|TEMP)))
  678.         free(n->stptr);
  679.     n->numbr = value;
  680.     n->flags |= (NUM|NUMERIC);
  681.     n->flags &= ~STR;
  682.     n->stref = 0;
  683.     deref = 0;
  684. }
  685.  
  686.  
  687. /* Is TREE true or false?  Returns 0==false, non-zero==true */
  688. static int
  689. eval_condition(tree)
  690. NODE *tree;
  691. {
  692.     register NODE *t1;
  693.     int ret;
  694.  
  695.     if (tree == NULL)    /* Null trees are the easiest kinds */
  696.         return 1;
  697.     if (tree->type == Node_line_range) {
  698.         /*
  699.          * Node_line_range is kind of like Node_match, EXCEPT: the
  700.          * lnode field (more properly, the condpair field) is a node
  701.          * of a Node_cond_pair; whether we evaluate the lnode of that
  702.          * node or the rnode depends on the triggered word.  More
  703.          * precisely:  if we are not yet triggered, we tree_eval the
  704.          * lnode; if that returns true, we set the triggered word. 
  705.          * If we are triggered (not ELSE IF, note), we tree_eval the
  706.          * rnode, clear triggered if it succeeds, and perform our
  707.          * action (regardless of success or failure).  We want to be
  708.          * able to begin and end on a single input record, so this
  709.          * isn't an ELSE IF, as noted above.
  710.          */
  711.         if (!tree->triggered)
  712.         {
  713.             if (!eval_condition(tree->condpair->lnode))
  714.                 return 0;
  715.             else
  716.                 tree->triggered = 1;
  717.         }
  718.         /* Else we are triggered */
  719.         if (eval_condition(tree->condpair->rnode))
  720.             tree->triggered = 0;
  721.         return 1;
  722.     }
  723.  
  724.     /*
  725.      * Could just be J.random expression. in which case, null and 0 are
  726.      * false, anything else is true 
  727.      */
  728.  
  729.     t1 = tree_eval(tree);
  730.     if (t1->flags & NUMERIC)
  731.         ret = t1->numbr != 0.0;
  732.     else
  733.         ret = t1->stlen != 0;
  734.     free_temp(t1);
  735.     return ret;
  736. }
  737.  
  738. int
  739. cmp_nodes(t1, t2)
  740. NODE *t1, *t2;
  741. {
  742.     AWKNUM d;
  743.     AWKNUM d1;
  744.     AWKNUM d2;
  745.     int ret;
  746.     int len1, len2;
  747.  
  748.     if (t1 == t2)
  749.         return 0;
  750.     d1 = force_number(t1);
  751.     d2 = force_number(t2);
  752.     if ((t1->flags & NUMERIC) && (t2->flags & NUMERIC)) {
  753.         d = d1 - d2;
  754.         if (d == 0.0)    /* from profiling, this is most common */
  755.             return 0;
  756.         if (d > 0.0)
  757.             return 1;
  758.         return -1;
  759.     }
  760.     t1 = force_string(t1);
  761.     t2 = force_string(t2);
  762.     len1 = t1->stlen;
  763.     len2 = t2->stlen;
  764.     if (len1 == 0) {
  765.         if (len2 == 0)
  766.             return 0;
  767.         else
  768.             return -1;
  769.     } else if (len2 == 0)
  770.         return 1;
  771.     ret = memcmp(t1->stptr, t2->stptr, len1 <= len2 ? len1 : len2);
  772.     if (ret == 0 && len1 != len2)
  773.         return len1 < len2 ? -1: 1;
  774.     return ret;
  775. }
  776.  
  777. static NODE *
  778. op_assign(tree)
  779. NODE *tree;
  780. {
  781.     AWKNUM rval, lval;
  782.     NODE **lhs;
  783.     AWKNUM t1, t2;
  784.     long ltemp;
  785.     NODE *tmp;
  786.  
  787.     lhs = get_lhs(tree->lnode, 1);
  788.     lval = force_number(*lhs);
  789.  
  790.     switch(tree->type) {
  791.     case Node_preincrement:
  792.     case Node_predecrement:
  793.         DBG_P(("+-X", tree));
  794.         assign_number(lhs,
  795.             lval + (tree->type == Node_preincrement ? 1.0 : -1.0));
  796.         do_deref();
  797.         if (field_num == 0)
  798.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  799.         field_num = -1;
  800.         return *lhs;
  801.  
  802.     case Node_postincrement:
  803.     case Node_postdecrement:
  804.         DBG_P(("X+-", tree));
  805.         assign_number(lhs,
  806.             lval + (tree->type == Node_postincrement ? 1.0 : -1.0));
  807.         do_deref();
  808.         if (field_num == 0)
  809.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  810.         field_num = -1;
  811.         return tmp_number(lval);
  812.     default:
  813.         break;    /* handled below */
  814.     }
  815.  
  816.     tmp = tree_eval(tree->rnode);
  817.     rval = force_number(tmp);
  818.     free_temp(tmp);
  819.     switch(tree->type) {
  820.     case Node_assign_exp:
  821.         DBG_P(("ASSIGN_exp", tree));
  822.         if ((ltemp = rval) == rval) {    /* integer exponent */
  823.             if (ltemp == 0)
  824.                 assign_number(lhs, (AWKNUM) 1);
  825.             else if (ltemp == 1)
  826.                 assign_number(lhs, lval);
  827.             else {
  828.                 /* doing it this way should be more precise */
  829.                 for (t1 = t2 = lval; --ltemp; )
  830.                     t1 *= t2;
  831.                 assign_number(lhs, t1);
  832.             }
  833.         } else
  834.             assign_number(lhs, (AWKNUM) pow((double) lval, (double) rval));
  835.         break;
  836.  
  837.     case Node_assign_times:
  838.         DBG_P(("ASSIGN_times", tree));
  839.         assign_number(lhs, lval * rval);
  840.         break;
  841.  
  842.     case Node_assign_quotient:
  843.         DBG_P(("ASSIGN_quotient", tree));
  844.         if (rval == (AWKNUM) 0)
  845.             fatal("division by zero attempted in /=");
  846.         assign_number(lhs, lval / rval);
  847.         break;
  848.  
  849.     case Node_assign_mod:
  850.         DBG_P(("ASSIGN_mod", tree));
  851.         if (rval == (AWKNUM) 0)
  852.             fatal("division by zero attempted in %=");
  853.         ltemp = lval / rval;    /* assignment to long truncates */
  854.         t1 = ltemp * rval;
  855.         t2 = lval - t1;
  856.         assign_number(lhs, t2);
  857.         break;
  858.  
  859.     case Node_assign_plus:
  860.         DBG_P(("ASSIGN_plus", tree));
  861.         assign_number(lhs, lval + rval);
  862.         break;
  863.  
  864.     case Node_assign_minus:
  865.         DBG_P(("ASSIGN_minus", tree));
  866.         assign_number(lhs, lval - rval);
  867.         break;
  868.     default:
  869.         cant_happen();
  870.     }
  871.     do_deref();
  872.     if (field_num == 0)
  873.         set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  874.     field_num = -1;
  875.     return *lhs;
  876. }
  877.  
  878. NODE **stack_ptr;
  879.  
  880. static NODE *
  881. func_call(name, arg_list)
  882. NODE *name;        /* name is a Node_val giving function name */
  883. NODE *arg_list;        /* Node_expression_list of calling args. */
  884. {
  885.     register NODE *arg, *argp, *r;
  886.     NODE *n, *f;
  887.     volatile jmp_buf func_tag_stack;
  888.     volatile jmp_buf loop_tag_stack;
  889.     volatile int save_loop_tag_valid = 0;
  890.     volatile NODE **save_stack, *save_ret_node;
  891.     NODE **local_stack, **sp;
  892.     int count;
  893.     extern NODE *ret_node;
  894.  
  895.     /*
  896.      * retrieve function definition node
  897.      */
  898.     f = lookup(variables, name->stptr);
  899.     if (!f || f->type != Node_func)
  900.         fatal("function `%s' not defined", name->stptr);
  901. #ifdef FUNC_TRACE
  902.     fprintf(stderr, "function %s called\n", name->stptr);
  903. #endif
  904.     count = f->lnode->param_cnt;
  905.     emalloc(local_stack, NODE **, count * sizeof(NODE *), "func_call");
  906.     sp = local_stack;
  907.  
  908.     /*
  909.      * for each calling arg. add NODE * on stack
  910.      */
  911.     for (argp = arg_list; count && argp != NULL; argp = argp->rnode) {
  912.         arg = argp->lnode;
  913.         r = newnode(Node_var);
  914.         /*
  915.          * call by reference for arrays; see below also
  916.          */
  917.         if (arg->type == Node_param_list)
  918.             arg = stack_ptr[arg->param_cnt];
  919.         if (arg->type == Node_var_array)
  920.             *r = *arg;
  921.         else {
  922.             n = tree_eval(arg);
  923.             r->lnode = dupnode(n);
  924.             r->rnode = (NODE *) NULL;
  925.             free_temp(n);
  926.           }
  927.         *sp++ = r;
  928.         count--;
  929.     }
  930.     if (argp != NULL)    /* left over calling args. */
  931.         warning(
  932.             "function `%s' called with more arguments than declared",
  933.             name->stptr);
  934.     /*
  935.      * add remaining params. on stack with null value
  936.      */
  937.     while (count-- > 0) {
  938.         r = newnode(Node_var);
  939.         r->lnode = Nnull_string;
  940.         r->rnode = (NODE *) NULL;
  941.         *sp++ = r;
  942.     }
  943.  
  944.     /*
  945.      * Execute function body, saving context, as a return statement
  946.      * will longjmp back here.
  947.      *
  948.      * Have to save and restore the loop_tag stuff so that a return
  949.      * inside a loop in a function body doesn't scrog any loops going
  950.      * on in the main program.  We save the necessary info in variables
  951.      * local to this function so that function nesting works OK.
  952.      * We also only bother to save the loop stuff if we're in a loop
  953.      * when the function is called.
  954.      */
  955.     if (loop_tag_valid) {
  956.         int junk = 0;
  957.  
  958.         save_loop_tag_valid = (volatile int) loop_tag_valid;
  959.         PUSH_BINDING(loop_tag_stack, loop_tag, junk);
  960.         loop_tag_valid = 0;
  961.     }
  962.     save_stack = (volatile NODE **) stack_ptr;
  963.     stack_ptr = local_stack;
  964.     PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);
  965.     save_ret_node = (volatile NODE *) ret_node;
  966.     ret_node = Nnull_string;    /* default return value */
  967.     if (setjmp(func_tag) == 0)
  968.         (void) interpret(f->rnode);
  969.  
  970.     r = ret_node;
  971.     ret_node = (NODE *) save_ret_node;
  972.     RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);
  973.     stack_ptr = (NODE **) save_stack;
  974.  
  975.     /*
  976.      * here, we pop each parameter and check whether
  977.      * it was an array.  If so, and if the arg. passed in was
  978.      * a simple variable, then the value should be copied back.
  979.      * This achieves "call-by-reference" for arrays.
  980.      */
  981.     sp = local_stack;
  982.     count = f->lnode->param_cnt;
  983.     for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {
  984.         arg = argp->lnode;
  985.         n = *sp++;
  986.         if (arg->type == Node_var && n->type == Node_var_array) {
  987.             arg->var_array = n->var_array;
  988.             arg->type = Node_var_array;
  989.         }
  990.         deref = n->lnode;
  991.         do_deref();
  992.         freenode(n);
  993.         count--;
  994.     }
  995.     while (count-- > 0) {
  996.         n = *sp++;
  997.         deref = n->lnode;
  998.         do_deref();
  999.         freenode(n);
  1000.     }
  1001.     free((char *) local_stack);
  1002.  
  1003.     /* Restore the loop_tag stuff if necessary. */
  1004.     if (save_loop_tag_valid) {
  1005.         int junk = 0;
  1006.  
  1007.         loop_tag_valid = (int) save_loop_tag_valid;
  1008.         RESTORE_BINDING(loop_tag_stack, loop_tag, junk);
  1009.     }
  1010.  
  1011.     if (!(r->flags & PERM))
  1012.         r->flags |= TEMP;
  1013.     return r;
  1014. }
  1015.  
  1016. /*
  1017.  * This returns a POINTER to a node pointer. get_lhs(ptr) is the current
  1018.  * value of the var, or where to store the var's new value 
  1019.  */
  1020.  
  1021. NODE **
  1022. get_lhs(ptr, assign)
  1023. NODE *ptr;
  1024. int assign;        /* this is being called for the LHS of an assign. */
  1025. {
  1026.     register NODE **aptr;
  1027.     NODE *n;
  1028.  
  1029. #ifdef DEBUG
  1030.     if (ptr == NULL)
  1031.         cant_happen();
  1032. #endif
  1033.     deref = NULL;
  1034.     field_num = -1;
  1035.     switch (ptr->type) {
  1036.     case Node_var:
  1037.     case Node_var_array:
  1038.         if (ptr == NF_node && (int) NF_node->var_value->numbr == -1)
  1039.             (void) get_field(HUGE-1, assign); /* parse record */
  1040.         deref = ptr->var_value;
  1041. #ifdef DEBUG
  1042.         if (deref->type != Node_val)
  1043.             cant_happen();
  1044.         if (deref->flags == 0)
  1045.             cant_happen();
  1046. #endif
  1047.         return &(ptr->var_value);
  1048.  
  1049.     case Node_param_list:
  1050.         n = stack_ptr[ptr->param_cnt];
  1051.         deref = n->var_value;
  1052. #ifdef DEBUG
  1053.         if (deref->type != Node_val)
  1054.             cant_happen();
  1055.         if (deref->flags == 0)
  1056.             cant_happen();
  1057. #endif
  1058.         return &(n->var_value);
  1059.  
  1060.     case Node_field_spec:
  1061.         n = tree_eval(ptr->lnode);
  1062.         field_num = (int) force_number(n);
  1063.         free_temp(n);
  1064.         if (field_num < 0)
  1065.             fatal("attempt to access field %d", field_num);
  1066.         aptr = get_field(field_num, assign);
  1067.         deref = *aptr;
  1068.         return aptr;
  1069.  
  1070.     case Node_subscript:
  1071.         n = ptr->lnode;
  1072.         if (n->type == Node_param_list)
  1073.             n = stack_ptr[n->param_cnt];
  1074.         aptr = assoc_lookup(n, concat_exp(ptr->rnode));
  1075.         deref = *aptr;
  1076. #ifdef DEBUG
  1077.         if (deref->type != Node_val)
  1078.             cant_happen();
  1079.         if (deref->flags == 0)
  1080.             cant_happen();
  1081. #endif
  1082.         return aptr;
  1083.     case Node_func:
  1084.         fatal ("`%s' is a function, assignment is not allowed",
  1085.             ptr->lnode->param);
  1086.     default:
  1087.         cant_happen();
  1088.     }
  1089.     return 0;
  1090. }
  1091.  
  1092. static NODE *
  1093. match_op(tree)
  1094. NODE *tree;
  1095. {
  1096.     NODE *t1;
  1097.     struct re_pattern_buffer *rp;
  1098.     int i;
  1099.     int match = 1;
  1100.  
  1101.     if (tree->type == Node_nomatch)
  1102.         match = 0;
  1103.     if (tree->type == Node_regex)
  1104.         t1 = WHOLELINE;
  1105.     else {
  1106.         if (tree->lnode)
  1107.             t1 = force_string(tree_eval(tree->lnode));
  1108.         else
  1109.             t1 = WHOLELINE;
  1110.         tree = tree->rnode;
  1111.     }
  1112.     if (tree->type == Node_regex) {
  1113.         rp = tree->rereg;
  1114.         if (!strict && ((IGNORECASE_node->var_value->numbr != 0)
  1115.             ^ (tree->re_case != 0))) {
  1116.             /* recompile since case sensitivity differs */
  1117.             rp = tree->rereg =
  1118.                 mk_re_parse(tree->re_text,
  1119.                 (IGNORECASE_node->var_value->numbr != 0));
  1120.             tree->re_case =
  1121.                 (IGNORECASE_node->var_value->numbr != 0);
  1122.         }
  1123.     } else {
  1124.         rp = make_regexp(force_string(tree_eval(tree)),
  1125.             (IGNORECASE_node->var_value->numbr != 0));
  1126.         if (rp == NULL)
  1127.             cant_happen();
  1128.     }
  1129.     i = re_search(rp, t1->stptr, t1->stlen, 0, t1->stlen,
  1130.         (struct re_registers *) NULL);
  1131.     i = (i == -1) ^ (match == 1);
  1132.     free_temp(t1);
  1133.     if (tree->type != Node_regex) {
  1134.         free(rp->buffer);
  1135.         free(rp->fastmap);
  1136.         free((char *) rp);
  1137.     }
  1138.     return tmp_number((AWKNUM) i);
  1139. }
  1140.